所以我想说我想写一本字典.我们称之为d
.但是有多种方法可以在Python中初始化字典!例如,我可以这样做:
d = {'hash': 'bang', 'slash': 'dot'}
或者我可以这样做:
d = dict(hash='bang', slash='dot')
或者,奇怪的是:
d = dict({'hash': 'bang', 'slash': 'dot'})
或这个:
d = dict([['hash', 'bang'], ['slash', 'dot']])
以及其他多种方式的dict()
功能.显然,dict()
提供的一件事是语法和初始化的灵活性.但这不是我要问的问题.
说我d
只做一本空字典.当我做什么那张Python解释器的幕后d = {}
对d = dict()
?它只是两种方式来做同样的事情?使用是否{}
有额外的电话dict()
?是否有一个(甚至可以忽略不计)比另一个更多的开销?虽然这个问题真的完全不重要,但我很乐意回答这个好奇心.
>>> def f(): ... return {'a' : 1, 'b' : 2} ... >>> def g(): ... return dict(a=1, b=2) ... >>> g() {'a': 1, 'b': 2} >>> f() {'a': 1, 'b': 2} >>> import dis >>> dis.dis(f) 2 0 BUILD_MAP 0 3 DUP_TOP 4 LOAD_CONST 1 ('a') 7 LOAD_CONST 2 (1) 10 ROT_THREE 11 STORE_SUBSCR 12 DUP_TOP 13 LOAD_CONST 3 ('b') 16 LOAD_CONST 4 (2) 19 ROT_THREE 20 STORE_SUBSCR 21 RETURN_VALUE >>> dis.dis(g) 2 0 LOAD_GLOBAL 0 (dict) 3 LOAD_CONST 1 ('a') 6 LOAD_CONST 2 (1) 9 LOAD_CONST 3 ('b') 12 LOAD_CONST 4 (2) 15 CALL_FUNCTION 512 18 RETURN_VALUE
dict()显然是一些C内置的.一个非常聪明或专注的人(不是我)可以查看翻译来源并告诉你更多.我只想展示dis.dis.:)
就性能而言:
>>> from timeit import timeit >>> timeit("a = {'a': 1, 'b': 2}") 0.424... >>> timeit("a = dict(a = 1, b = 2)") 0.889...
@Jacob:对象的分配方式有所不同,但它们不是写时复制.Python分配一个固定大小的"空闲列表",它可以快速分配字典对象(直到它填满).通过{}
语法(或C调用PyDict_New
)分配的字典可以来自此空闲列表.当字典不再被引用时,它将返回到空闲列表,并且可以重用该内存块(尽管首先重置字段).
第一个字典立即返回到空闲列表,下一个将重用其内存空间:
>>> id({}) 340160 >>> id({1: 2}) 340160
如果您保留引用,则下一个字典将来自下一个空闲槽:
>>> x = {} >>> id(x) 340160 >>> id({}) 340016
但我们可以删除对该字典的引用并再次释放其插槽:
>>> del x >>> id({}) 340160
由于{}
语法是用字节码处理的,因此它可以使用上面提到的这种优化.另一方面dict()
,像常规类构造函数一样处理,Python使用通用内存分配器,它不遵循像上面的空闲列表那样易于预测的模式.
另外,从Python 2.6查看compile.c,使用{}
语法似乎根据它存储的项目数量预先调整哈希表的大小,这在解析时是已知的.
基本上,{}是语法,在语言和字节码级别上处理.dict()只是另一种具有更灵活的初始化语法的内置函数.请注意,dict()仅添加在2.x系列的中间.
更新:感谢您的回复.删除了关于写时复制的猜测.
{}
和之间的另一个区别dict
是dict
总是分配一个新的字典(即使内容是静态的),{}
但并不总是如此(参见mgood关于何时和为什么的答案):
def dict1(): return {'a':'b'} def dict2(): return dict(a='b') print id(dict1()), id(dict1()) print id(dict2()), id(dict2())
生产:
$ ./mumble.py 11642752 11642752 11867168 11867456
我并不是说你试图利用这个与否,这取决于具体情况,只是指出来.(如果您了解操作码,也可能从反汇编中看出来).